package com.stud.seckill.common.aop;

import cn.hutool.core.util.StrUtil;
import com.stud.seckill.common.auth.UserContext;
import com.stud.seckill.common.config.RedisService;
import com.stud.seckill.common.enums.LockKeyEnum;
import com.stud.seckill.common.exception.Asserts;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import java.util.Collections;

/**
 * AOP
 */
@Aspect
@Component
public class AspectConfig {

    @Resource
    private RedisScript<Long> accessLimitScript;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 限制访问
     * @param joinPoint
     * @param accessLimit
     */
    @Before("@annotation(accessLimit)")
    public void accessLimit(JoinPoint joinPoint, AccessLimit accessLimit) {

        int second = accessLimit.second();
        int maxCount = accessLimit.maxCount();
        boolean needLogin = accessLimit.needLogin();

        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String url = requestAttributes == null ? null : requestAttributes.getRequest().getRequestURI();

        String key = LockKeyEnum.访问限制.getKey() + (StrUtil.isEmpty(url) ? className + ":" + methodName : url);
        if (needLogin) {
            if (UserContext.getUser() == null) {
                Asserts.fail("未登录");
            }
            key += ":" + UserContext.getUser().getId();
        }

        Long isR = redisTemplate.execute(accessLimitScript, Collections.singletonList(key), maxCount, second);
        if (isR == null || isR == 0) {
            Asserts.fail("操作频繁");
        }

    }

}
